local sk__langxi = fk.CreateSkill {

  name = "sk__langxi",

  tags = {},

}



sk__langxi:addEffect(fk.GameStart, {
  name = "sk__langxi",
  mute = true,
  events = { fk.GameStart, fk.CardUsing, fk.CardUseFinished },
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__langxi.name) then
      return true
    end
  end,
  on_cost = function(self, event, target, player, data)
    return true
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(sk__langxi.name)
    local mark = player:getTableMark("@$sk__langxi")
    local choices, all_names = {}, {}
    for _, id in ipairs(Fk:getAllCardIds()) do
      local card = Fk:getCardById(id)
      if card:isCommonTrick() and not card.is_derived then
        table.insertIfNeed(all_names, card.trueName)
        if not table.contains(mark, card.trueName) then
          table.insertIfNeed(choices, card.trueName)
        end
      end
    end
    if #choices == 0 then return end
    room:notifySkillInvoked(player, sk__langxi.name, "special")
    local choice = room:askForChoice(player, choices, sk__langxi.name, "#sk__langxi-choice", false, all_names)
    table.insert(mark, choice)
    room:setPlayerMark(player, "@$sk__langxi", mark)
  end,
})
sk__langxi:addEffect(fk.CardUsing, {
  name = "sk__langxi",
  mute = true,
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__langxi.name) then
      if target == player and data.card:isCommonTrick() and data:isUsingHandcard(player) then
        return not table.contains(player:getTableMark("@$sk__langxi"), data.card.trueName)
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    return player.room:askForSkillInvoke(player, sk__langxi.name, nil, "#sk__langxi-record:::" .. data.card.trueName)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(sk__langxi.name)
    local mark = player:getTableMark("@$sk__langxi")
    table.insert(mark, data.card.trueName)
    room:setPlayerMark(player, "@$sk__langxi", mark)
  end,
})
sk__langxi:addEffect(fk.CardUseFinished, {
  name = "sk__langxi",
  mute = true,
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(sk__langxi.name) then
      if target == player and data.card:isCommonTrick() and data:isUsingHandcard(player) then
        return data.tos and table.find(data.tos, function(id)
          return not id.dead
        end) and #player:getTableMark("@$sk__langxi") > 0
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local targets = data.tos
    local tos = player.room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1,
      math.min(#targets, #player:getTableMark("@$sk__langxi")),
      "#sk__langxi-invoke", sk__langxi.name)
    if #tos > 0 then
      event:setCostData(self, tos)
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(sk__langxi.name)
    local mark = player:getTableMark("@$sk__langxi")
    room:notifySkillInvoked(player, sk__langxi.name, "offensive")
    local targets = table.map(event:getCostData(self), Util.Id2PlayerMapper)
    room:sortByAction(targets)

    for index, target_p in ipairs(targets) do
      for index, card_name in ipairs(mark) do
        if player.dead or target_p.dead then return end
        local card = Fk:cloneCard(card_name)
        card.skillName = sk__langxi.name
        local canUse = player:canUseTo(card, target_p, { bypass_distances = true, bypass_times = true })
        if canUse then
          local use = {
            from = player,
            tos = { target_p },
            card = card,
            extraUse = true,
          }
          room:useCard(use)
        end
      end
    end
  end,
})

sk__langxi:addLoseEffect(function(self, player, is_death)
  local room = player.room
  room:setPlayerMark(player, "@$sk__langxi", 0)
end)

sk__langxi:addEffect(fk.Deathed, {
  can_refresh = function(self, event, target, player, data)
    if target == player then
      return player:hasSkill(self, true, true)
    end
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:setPlayerMark(player, "@$sk__langxi", 0)
  end,
})

return sk__langxi
